/**
 * 字符串模块 - 借鉴Lodash的字符串处理理念
 * 提供各种字符串操作和处理功能
 */

// 字符集定义
const CHAR_SETS = {
  numbers: '0123456789',
  letters: 'abcdefghijklmnopqrstuvwxyz',
  lettersUpper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  symbols: '!@#$%^&*()_+-=[]{}|;:,.<>?',
  chinese: '零一二三四五六七八九十百千万亿'
};

const ALL_CHARS = CHAR_SETS.numbers + CHAR_SETS.letters + CHAR_SETS.lettersUpper;

/**
 * 移除null值，转换为空字符串
 * @param {any} value 要处理的值
 * @returns {string} 处理后的字符串
 */
export function removeNull(value) {
  if (value === null ||
      value === undefined ||
      value === 'null' ||
      value === 'undefined' ||
      value === 'NULL' ||
      typeof value === 'undefined') {
    return '';
  }
  return String(value);
}

/**
 * 生成随机字符串
 * @param {number} length 长度
 * @param {number} type 类型：1=数字字母混合，2=纯数字，3=纯字母，4=包含符号
 * @returns {string} 随机字符串
 */
export function randomString(length = 6, type = 1) {
  if (typeof length !== 'number' || length <= 0) return '';

  let chars = '';
  switch (type) {
    case 1:
      chars = ALL_CHARS;
      break;
    case 2:
      chars = CHAR_SETS.numbers;
      break;
    case 3:
      chars = CHAR_SETS.letters + CHAR_SETS.lettersUpper;
      break;
    case 4:
      chars = ALL_CHARS + CHAR_SETS.symbols;
      break;
    default:
      chars = ALL_CHARS;
  }

  let result = '';
  for (let i = 0; i < length; i++) {
    result += chars[Math.floor(Math.random() * chars.length)];
  }

  return result;
}

/**
 * 获取用户显示名称
 * @param {string} username 用户名
 * @param {string} realname 真实姓名
 * @returns {string} 显示名称
 */
export function getName(username, realname) {
  if (realname && realname !== '' && realname !== 'null') {
    return String(realname);
  }
  return username ? String(username) : '';
}

/**
 * 获取用户头像路径
 * @param {string} avatar 头像文件名
 * @param {string} basePath 基础路径
 * @returns {string} 完整头像路径
 */
export function getUserPic(avatar, basePath = '../image/') {
  const defaultPic = basePath + 'default_user_portrait.gif';

  if (!avatar || avatar === '' || avatar === 'null') {
    return defaultPic;
  }

  // 如果已经是完整URL，直接返回
  if (avatar.startsWith('http') || avatar.startsWith('//')) {
    return avatar;
  }

  return basePath + 'avatar/' + avatar;
}

/**
 * 首字母大写
 * @param {string} str 字符串
 * @returns {string} 首字母大写的字符串
 */
export function capitalize(str) {
  if (typeof str !== 'string' || str.length === 0) return '';
  return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}

/**
 * 驼峰命名转换
 * @param {string} str 字符串
 * @returns {string} 驼峰命名字符串
 */
export function camelCase(str) {
  if (typeof str !== 'string') return '';

  return str
    .replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '')
    .replace(/^./, c => c.toLowerCase());
}

/**
 * 帕斯卡命名转换
 * @param {string} str 字符串
 * @returns {string} 帕斯卡命名字符串
 */
export function pascalCase(str) {
  if (typeof str !== 'string') return '';

  const camelCased = camelCase(str);
  return camelCased.charAt(0).toUpperCase() + camelCased.slice(1);
}

/**
 * 短横线命名转换
 * @param {string} str 字符串
 * @returns {string} 短横线命名字符串
 */
export function kebabCase(str) {
  if (typeof str !== 'string') return '';

  return str
    .replace(/([A-Z])/g, '-$1')
    .replace(/[-_\s]+/g, '-')
    .toLowerCase()
    .replace(/^-/, '');
}

/**
 * 下划线命名转换
 * @param {string} str 字符串
 * @returns {string} 下划线命名字符串
 */
export function snakeCase(str) {
  if (typeof str !== 'string') return '';

  return str
    .replace(/([A-Z])/g, '_$1')
    .replace(/[-\s]+/g, '_')
    .toLowerCase()
    .replace(/^_/, '');
}

/**
 * 截断字符串
 * @param {string} str 字符串
 * @param {number} length 长度
 * @param {string} omission 省略标记
 * @returns {string} 截断后的字符串
 */
export function truncate(str, length = 30, omission = '...') {
  if (typeof str !== 'string') return '';

  if (str.length <= length) return str;

  return str.slice(0, length - omission.length) + omission;
}

/**
 * 移除字符串两端空格
 * @param {string} str 字符串
 * @param {string} chars 要移除的字符
 * @returns {string} 处理后的字符串
 */
export function trim(str, chars) {
  if (typeof str !== 'string') return '';

  if (chars === undefined) {
    return str.trim();
  }

  const pattern = new RegExp(`^[${escapeRegExp(chars)}]+|[${escapeRegExp(chars)}]+$`, 'g');
  return str.replace(pattern, '');
}

/**
 * 填充字符串左侧
 * @param {string} str 字符串
 * @param {number} length 目标长度
 * @param {string} chars 填充字符
 * @returns {string} 填充后的字符串
 */
export function padStart(str, length, chars = ' ') {
  if (typeof str !== 'string') str = String(str);

  if (str.length >= length) return str;

  const padLength = length - str.length;
  const pad = chars.repeat(Math.ceil(padLength / chars.length)).slice(0, padLength);

  return pad + str;
}

/**
 * 填充字符串右侧
 * @param {string} str 字符串
 * @param {number} length 目标长度
 * @param {string} chars 填充字符
 * @returns {string} 填充后的字符串
 */
export function padEnd(str, length, chars = ' ') {
  if (typeof str !== 'string') str = String(str);

  if (str.length >= length) return str;

  const padLength = length - str.length;
  const pad = chars.repeat(Math.ceil(padLength / chars.length)).slice(0, padLength);

  return str + pad;
}

/**
 * 重复字符串
 * @param {string} str 字符串
 * @param {number} count 重复次数
 * @returns {string} 重复后的字符串
 */
export function repeat(str, count = 1) {
  if (typeof str !== 'string') return '';
  if (typeof count !== 'number' || count < 0) return '';

  return str.repeat(Math.floor(count));
}

/**
 * 反转字符串
 * @param {string} str 字符串
 * @returns {string} 反转后的字符串
 */
export function reverse(str) {
  if (typeof str !== 'string') return '';
  return str.split('').reverse().join('');
}

/**
 * 计算字符串显示宽度（中文字符算2个宽度）
 * @param {string} str 字符串
 * @returns {number} 显示宽度
 */
export function displayWidth(str) {
  if (typeof str !== 'string') return 0;

  let width = 0;
  for (let i = 0; i < str.length; i++) {
    const charCode = str.charCodeAt(i);
    // 中文字符范围
    if ((charCode >= 0x4e00 && charCode <= 0x9fff) ||
        (charCode >= 0x3400 && charCode <= 0x4dbf) ||
        (charCode >= 0x20000 && charCode <= 0x2a6df) ||
        (charCode >= 0x2a700 && charCode <= 0x2b73f) ||
        (charCode >= 0x2b740 && charCode <= 0x2b81f) ||
        (charCode >= 0x2b820 && charCode <= 0x2ceaf) ||
        (charCode >= 0xf900 && charCode <= 0xfaff) ||
        (charCode >= 0x2f800 && charCode <= 0x2fa1f)) {
      width += 2;
    } else {
      width += 1;
    }
  }
  return width;
}

/**
 * 按显示宽度截断字符串
 * @param {string} str 字符串
 * @param {number} maxWidth 最大显示宽度
 * @param {string} omission 省略标记
 * @returns {string} 截断后的字符串
 */
export function truncateByWidth(str, maxWidth, omission = '...') {
  if (typeof str !== 'string') return '';

  const omissionWidth = displayWidth(omission);
  let currentWidth = 0;
  let result = '';

  for (let i = 0; i < str.length; i++) {
    const char = str[i];
    const charWidth = displayWidth(char);

    if (currentWidth + charWidth > maxWidth - omissionWidth) {
      return result + omission;
    }

    result += char;
    currentWidth += charWidth;
  }

  return result;
}

/**
 * 转换为拼音首字母
 * @param {string} str 中文字符串
 * @returns {string} 拼音首字母
 */
export function toPinyin(str) {
  if (typeof str !== 'string') return '';

  // 简单的拼音映射（实际项目中建议使用专门的拼音库）
  const pinyinMap = {
    '阿': 'A', '安': 'A', '按': 'A', '暗': 'A', '昂': 'A',
    '八': 'B', '白': 'B', '百': 'B', '班': 'B', '办': 'B', '帮': 'B', '包': 'B', '保': 'B', '报': 'B', '北': 'B', '本': 'B', '比': 'B', '边': 'B', '表': 'B', '别': 'B', '并': 'B', '部': 'B', '不': 'B',
    '草': 'C', '曹': 'C', '层': 'C', '常': 'C', '车': 'C', '成': 'C', '程': 'C', '出': 'C', '初': 'C', '处': 'C', '川': 'C', '传': 'C', '创': 'C', '从': 'C', '存': 'C',
    '大': 'D', '代': 'D', '当': 'D', '到': 'D', '的': 'D', '地': 'D', '点': 'D', '电': 'D', '东': 'D', '动': 'D', '都': 'D', '对': 'D', '多': 'D', '度': 'D', '但': 'D', '打': 'D', '带': 'D', '单': 'D', '道': 'D', '得': 'D', '第': 'D', '定': 'D', '董': 'D',
    '二': 'E', '儿': 'E', '而': 'E',
    '发': 'F', '法': 'F', '方': 'F', '放': 'F', '非': 'F', '分': 'F', '风': 'F', '服': 'F', '府': 'F', '副': 'F', '复': 'F', '富': 'F', '父': 'F', '妇': 'F',
    '个': 'G', '给': 'G', '根': 'G', '跟': 'G', '更': 'G', '工': 'G', '公': 'G', '古': 'G', '关': 'G', '管': 'G', '广': 'G', '国': 'G', '过': 'G', '高': 'G', '各': 'G', '感': 'G', '刚': 'G', '告': 'G', '歌': 'G', '格': 'G', '共': 'G', '构': 'G',
    '海': 'H', '还': 'H', '好': 'H', '号': 'H', '和': 'H', '黑': 'H', '很': 'H', '红': 'H', '后': 'H', '户': 'H', '花': 'H', '华': 'H', '画': 'H', '话': 'H', '换': 'H', '黄': 'H', '回': 'H', '会': 'H', '活': 'H', '火': 'H', '或': 'H', '获': 'H', '合': 'H', '何': 'H', '河': 'H', '候': 'H', '护': 'H',
    '机': 'J', '基': 'J', '级': 'J', '及': 'J', '家': 'J', '加': 'J', '间': 'J', '见': 'J', '建': 'J', '江': 'J', '将': 'J', '交': 'J', '教': 'J', '叫': 'J', '接': 'J', '街': 'J', '节': 'J', '结': 'J', '解': 'J', '进': 'J', '金': 'J', '今': 'J', '经': 'J', '京': 'J', '九': 'J', '就': 'J', '局': 'J', '决': 'J', '军': 'J', '究': 'J', '具': 'J', '据': 'J',
    '开': 'K', '看': 'K', '可': 'K', '科': 'K', '空': 'K', '口': 'K', '快': 'K', '客': 'K', '课': 'K', '考': 'K',
    '来': 'L', '老': 'L', '了': 'L', '类': 'L', '里': 'L', '理': 'L', '立': 'L', '利': 'L', '连': 'L', '联': 'L', '两': 'L', '林': 'L', '六': 'L', '龙': 'L', '路': 'L', '力': 'L', '历': 'L', '领': 'L', '流': 'L', '留': 'L', '论': 'L', '落': 'L',
    '马': 'M', '么': 'M', '没': 'M', '美': 'M', '门': 'M', '们': 'M', '民': 'M', '名': 'M', '明': 'M', '木': 'M', '目': 'M', '面': 'M', '买': 'M', '卖': 'M', '满': 'M', '慢': 'M', '毛': 'M', '米': 'M', '母': 'M',
    '那': 'N', '南': 'N', '内': 'N', '能': 'N', '你': 'N', '年': 'N', '农': 'N', '女': 'N', '难': 'N', '脑': 'N', '拿': 'N', '男': 'N', '奶': 'N',
    '哦': 'O', '欧': 'O',
    '平': 'P', '片': 'P', '品': 'P', '普': 'P', '朋': 'P', '跑': 'P', '怕': 'P', '排': 'P', '派': 'P', '盘': 'P', '判': 'P', '培': 'P', '皮': 'P', '票': 'P', '破': 'P',
    '七': 'Q', '其': 'Q', '起': 'Q', '气': 'Q', '前': 'Q', '钱': 'Q', '强': 'Q', '青': 'Q', '清': 'Q', '去': 'Q', '全': 'Q', '群': 'Q', '请': 'Q', '情': 'Q', '求': 'Q', '取': 'Q', '确': 'Q', '切': 'Q', '区': 'Q',
    '人': 'R', '日': 'R', '如': 'R', '让': 'R', '认': 'R', '容': 'R', '入': 'R', '热': 'R', '任': 'R', '然': 'R', '肉': 'R', '软': 'R',
    '三': 'S', '色': 'S', '山': 'S', '上': 'S', '少': 'S', '社': 'S', '身': 'S', '深': 'S', '什': 'S', '生': 'S', '声': 'S', '十': 'S', '时': 'S', '实': 'S', '使': 'S', '是': 'S', '事': 'S', '市': 'S', '手': 'S', '首': 'S', '受': 'S', '书': 'S', '数': 'S', '水': 'S', '说': 'S', '四': 'S', '送': 'S', '苏': 'S', '所': 'S', '思': 'S', '司': 'S', '死': 'S', '算': 'S', '虽': 'S', '岁': 'S', '孙': 'S',
    '他': 'T', '她': 'T', '台': 'T', '太': 'T', '特': 'T', '天': 'T', '田': 'T', '条': 'T', '听': 'T', '同': 'T', '头': 'T', '土': 'T', '团': 'T', '推': 'T', '通': 'T', '统': 'T', '体': 'T', '提': 'T', '题': 'T', '图': 'T', '突': 'T', '退': 'T',
    '外': 'W', '完': 'W', '万': 'W', '王': 'W', '网': 'W', '往': 'W', '为': 'W', '位': 'W', '文': 'W', '我': 'W', '无': 'W', '五': 'W', '物': 'W', '问': 'W', '闻': 'W', '温': 'W', '务': 'W', '武': 'W', '舞': 'W', '误': 'W',
    '西': 'X', '系': 'X', '下': 'X', '先': 'X', '现': 'X', '线': 'X', '向': 'X', '想': 'X', '小': 'X', '些': 'X', '新': 'X', '信': 'X', '行': 'X', '星': 'X', '学': 'X', '雪': 'X', '选': 'X', '需': 'X', '许': 'X', '续': 'X', '血': 'X', '寻': 'X', '迅': 'X',
    '一': 'Y', '以': 'Y', '用': 'Y', '由': 'Y', '有': 'Y', '又': 'Y', '于': 'Y', '与': 'Y', '元': 'Y', '原': 'Y', '员': 'Y', '月': 'Y', '越': 'Y', '云': 'Y', '运': 'Y', '应': 'Y', '影': 'Y', '意': 'Y', '议': 'Y', '义': 'Y', '因': 'Y', '银': 'Y', '音': 'Y', '引': 'Y', '印': 'Y', '英': 'Y', '营': 'Y', '油': 'Y', '游': 'Y', '友': 'Y',
    '在': 'Z', '则': 'Z', '怎': 'Z', '增': 'Z', '展': 'Z', '站': 'Z', '张': 'Z', '章': 'Z', '找': 'Z', '这': 'Z', '着': 'Z', '真': 'Z', '正': 'Z', '政': 'Z', '之': 'Z', '知': 'Z', '直': 'Z', '只': 'Z', '制': 'Z', '治': 'Z', '中': 'Z', '种': 'Z', '重': 'Z', '周': 'Z', '主': 'Z', '住': 'Z', '专': 'Z', '转': 'Z', '装': 'Z', '状': 'Z', '子': 'Z', '字': 'Z', '自': 'Z', '总': 'Z', '走': 'Z', '组': 'Z', '最': 'Z', '作': 'Z', '做': 'Z', '早': 'Z', '造': 'Z', '责': 'Z', '者': 'Z', '整': 'Z', '证': 'Z', '支': 'Z', '资': 'Z', '准': 'Z'
  };

  return str.split('').map(char => pinyinMap[char] || char).join('');
}

/**
 * 正则表达式转义
 * @param {string} str 字符串
 * @returns {string} 转义后的字符串
 */
function escapeRegExp(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

/**
 * 导出正则表达式转义函数
 * @param {string} str 字符串
 * @returns {string} 转义后的字符串
 */
export { escapeRegExp };

/**
 * HTML转义
 * @param {string} str 字符串
 * @returns {string} 转义后的字符串
 */
export function escapeHtml(str) {
  if (typeof str !== 'string') return '';

  const htmlEscapes = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '/': '&#x2F;'
  };

  return str.replace(/[&<>"'/]/g, char => htmlEscapes[char]);
}

/**
 * HTML反转义
 * @param {string} str 字符串
 * @returns {string} 反转义后的字符串
 */
export function unescapeHtml(str) {
  if (typeof str !== 'string') return '';

  const htmlUnescapes = {
    '&amp;': '&',
    '&lt;': '<',
    '&gt;': '>',
    '&quot;': '"',
    '&#x27;': "'",
    '&#x2F;': '/'
  };

  return str.replace(/&(amp|lt|gt|quot|#x27|#x2F);/g, entity => htmlUnescapes[entity]);
}

/**
 * 生成UUID
 * @returns {string} UUID字符串
 */
export function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = Math.random() * 16 | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

/**
 * 生成短ID
 * @param {number} length 长度
 * @returns {string} 短ID
 */
export function generateShortId(length = 8) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let result = '';
  for (let i = 0; i < length; i++) {
    result += chars[Math.floor(Math.random() * chars.length)];
  }
  return result;
}

/**
 * 字符串hash
 * @param {string} str 字符串
 * @returns {number} hash值
 */
export function hashCode(str) {
  if (typeof str !== 'string') return 0;

  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // 转换为32位整数
  }
  return hash;
}

/**
 * 字符串模板
 * @param {string} template 模板字符串
 * @param {Object} data 数据对象
 * @returns {string} 替换后的字符串
 */
export function template(template, data) {
  if (typeof template !== 'string') return '';
  if (!data || typeof data !== 'object') return template;

  return template.replace(/\{\{\s*([^}]+)\s*\}\}/g, (match, key) => {
    const value = data[key.trim()];
    return value !== undefined ? String(value) : match;
  });
}

/**
 * 字符串分割（增强版）
 * @param {string} str 字符串
 * @param {string|RegExp} separator 分隔符
 * @param {number} limit 限制数量
 * @returns {string[]} 分割后的数组
 */
export function split(str, separator, limit) {
  if (typeof str !== 'string') return [];

  const result = str.split(separator, limit);
  return result.filter(item => item !== '');
}

/**
 * 字符串包含检查（忽略大小写）
 * @param {string} str 原字符串
 * @param {string} searchString 搜索字符串
 * @returns {boolean} 是否包含
 */
export function includesIgnoreCase(str, searchString) {
  if (typeof str !== 'string' || typeof searchString !== 'string') return false;
  return str.toLowerCase().includes(searchString.toLowerCase());
}

/**
 * 字符串开头检查（忽略大小写）
 * @param {string} str 原字符串
 * @param {string} searchString 搜索字符串
 * @returns {boolean} 是否以指定字符串开头
 */
export function startsWithIgnoreCase(str, searchString) {
  if (typeof str !== 'string' || typeof searchString !== 'string') return false;
  return str.toLowerCase().startsWith(searchString.toLowerCase());
}

/**
 * 字符串结尾检查（忽略大小写）
 * @param {string} str 原字符串
 * @param {string} searchString 搜索字符串
 * @returns {boolean} 是否以指定字符串结尾
 */
export function endsWithIgnoreCase(str, searchString) {
  if (typeof str !== 'string' || typeof searchString !== 'string') return false;
  return str.toLowerCase().endsWith(searchString.toLowerCase());
}

/**
 * 字符串编码
 * @param {string} str 字符串
 * @returns {string} 编码后的字符串
 */
export function encodeBase64(str) {
  if (typeof str !== 'string') return '';
  try {
    return btoa(unescape(encodeURIComponent(str)));
  } catch (e) {
    return '';
  }
}

/**
 * 字符串解码
 * @param {string} str Base64字符串
 * @returns {string} 解码后的字符串
 */
export function decodeBase64(str) {
  if (typeof str !== 'string') return '';
  try {
    return decodeURIComponent(escape(atob(str)));
  } catch (e) {
    return '';
  }
}

/**
 * 提取数字
 * @param {string} str 字符串
 * @returns {string[]} 数字数组
 */
export function extractNumbers(str) {
  if (typeof str !== 'string') return [];
  return str.match(/\d+/g) || [];
}

/**
 * 提取中文字符
 * @param {string} str 字符串
 * @returns {string} 中文字符
 */
export function extractChinese(str) {
  if (typeof str !== 'string') return '';
  const matches = str.match(/[\u4e00-\u9fa5]/g);
  return matches ? matches.join('') : '';
}

/**
 * 提取英文字符
 * @param {string} str 字符串
 * @returns {string} 英文字符
 */
export function extractEnglish(str) {
  if (typeof str !== 'string') return '';
  const matches = str.match(/[a-zA-Z]/g);
  return matches ? matches.join('') : '';
}

/**
 * 字符统计
 * @param {string} str 字符串
 * @returns {Object} 统计结果
 */
export function characterCount(str) {
  if (typeof str !== 'string') return {
    total: 0,
    chinese: 0,
    english: 0,
    number: 0,
    symbol: 0,
    space: 0
  };

  let chinese = 0, english = 0, number = 0, symbol = 0, space = 0;

  for (let i = 0; i < str.length; i++) {
    const char = str[i];
    if (/[\u4e00-\u9fa5]/.test(char)) {
      chinese++;
    } else if (/[a-zA-Z]/.test(char)) {
      english++;
    } else if (/\d/.test(char)) {
      number++;
    } else if (/\s/.test(char)) {
      space++;
    } else {
      symbol++;
    }
  }

  return {
    total: str.length,
    chinese,
    english,
    number,
    symbol,
    space
  };
}
